package com.wangsd.web.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import com.wangsd.common.basicbean.Result;
import com.wangsd.common.component.WeixinPayService;
import com.wangsd.common.component.WxPayServiceExt;
import com.wangsd.common.component.extBean.AuthinfoRequest;
import com.wangsd.common.component.extBean.AuthinfoResponse;
import com.wangsd.common.mq.MqSend;
import com.wangsd.common.socket.WebSocketServer;
import com.wangsd.common.utils.ApplicationUtils;
import com.wangsd.common.utils.HttpClientUtils;
import com.wangsd.common.utils.MD5Utils;
import com.wangsd.common.utils.PayUtil;
import com.wangsd.web.MyController;
import com.wangsd.web.face.entity.*;
import com.wangsd.web.face.service.*;
import com.wangsd.web.sys.entity.SysUser;
import com.wangsd.web.sys.service.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import static com.wangsd.common.enums.ResultCode.ACCOUNT_PASSWORD_ERROR;

/**
 * 安全放行的controller
 */
@Api(value = "faceApi", tags = "APP对接接口")
@Controller
@RequestMapping("/api/face")
@Slf4j
public class ApiController extends MyController {

    @Value("${service.url}")
    private String notifyUrl;
    @Value("${service.tyt.url}")
    private String tytUrl;

    @Autowired
    WeixinPayService weixinPayService;
    @Autowired
    DeviceService deviceService;
    @Autowired
    StoreService storeService;
    @Autowired
    MerchantService merchantService;
    @Autowired
    ServiceBusinessService serviceBusinessService;
    @Autowired
    TOrderService tOrderService;
    @Autowired
    AdvertisementService advertisementService;
    @Autowired
    MemberService memberService;
    @Autowired
    MemberLevelService memberLevelService;
    @Autowired
    CloseAccountService closeAccountService;
    @Autowired
    SysUserService sysUserService;
    @Autowired
    TradeNoService tradeNoService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    MqSend mqSend;

    @ApiOperation(value = "用户登录", notes = "用户登录", httpMethod = "POST", response = Result.class)
    @PostMapping("/login")
    @ResponseBody
    public Result login(@ApiParam(value = "用户名", required = true) @RequestParam("username") String username,
                        @ApiParam(value = "密码", required = true) @RequestParam("password") String password,
                        @ApiParam(value = "极光注册ID", required = true) @RequestParam("registrationId") String registrationId,
                        @ApiParam(value = "设备编号", required = true) @RequestParam("deviceNo") String deviceNo) {

        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            return new Result(ACCOUNT_PASSWORD_ERROR);
        }
        if(StringUtils.isBlank(registrationId)){
            return Result.fail("极光推送注册ID不能为空！");
        }
        Device device = deviceService.selectByDeviceNo(deviceNo);
        if (device == null) {
            return Result.fail("设备配置信息异常！");
        }
        //获取门店信息
        Store store = storeService.getById(device.getStoreId());
        if (store == null) {
            return Result.fail("门店配置信息异常！");
        }
        Merchant merchant = merchantService.getById(store.getMerchantId());
        if (merchant == null) {
            return Result.fail("商户配置信息异常！");
        }


        SysUser user = sysUserService.selectLogin(username, password);

        if (user != null) {
            if (user.getType() == 4) {
                if (user.getParentId() != store.getId()) {
                    return Result.fail("请登录对应门店账号");
                }
            } else if (user.getType() == 3) {
                if (user.getParentId() != merchant.getId()) {
                    return Result.fail("请登录对应商户账号");
                }
            } else {
                return Result.fail("请登录商户或门店账号");
            }

            //修改当前用户登录设备的极光推送注册ID
            user.setRegistrationId(registrationId);
            sysUserService.updateById(user);


            String token = UUID.randomUUID().toString().replace("-", "");

            /*模拟单点登录 --start*/
            Object objectToken = redisTemplate.opsForValue().get(user.getId().toString());
            if (objectToken != null) {
                String stringToken = (String) objectToken;
                redisTemplate.delete(stringToken);
            }
            redisTemplate.opsForValue().set(user.getId().toString(), token);
            /*模拟单点登录 --end*/

            redisTemplate.opsForValue().set(token, user, 12, TimeUnit.HOURS);
            Map<String, String> map = new HashMap<>();
            map.put("token", token);
            map.put("storeName", store.getName());
            map.put("username", user.getUsername());
            map.put("logoUrl", merchant.getLogoUrl());
            map.put("id", user.getId() + "");
            log.info("app登录返回用户信息" + JSON.toJSONString(map));
            return Result.success(map);
        }
        return new Result(ACCOUNT_PASSWORD_ERROR);

    }


    @ApiOperation(value = "修改密码", notes = "修改密码", httpMethod = "POST", response = Result.class)
    @PostMapping("/updatePassword")
    @ResponseBody
    public Result updatePassword(@ApiParam(value = "原密码", required = true) @RequestParam("oldPass") String oldPass,
                                 @ApiParam(value = "新密码", required = true) @RequestParam("newPass") String newPass) {

        SysUser user = getUserInfo();
        if (user == null) {
            return Result.fail("请登录收银员账号！！");
        }
        if (StringUtils.isBlank(oldPass) || StringUtils.isBlank(newPass)) {
            return Result.fail("原密码和新密码不能为空！");
        }

        SysUser newUser = sysUserService.getById(user.getId());
        if (!newUser.getPassword().equals(oldPass)) {
            return Result.fail("原密码错误！");
        }
        newUser.setPassword(newPass);
        sysUserService.updateById(newUser);
        return Result.success();

    }


    /**
     * 会员支付
     *
     * @param deviceNo  设备编号
     * @param totalFee  订单金额
     * @param subOpenId 会员号码
     * @return
     */
    @ApiOperation(value = "会员支付", notes = "会员支付", httpMethod = "POST")
    @RequestMapping(value = "/memberPay", method = RequestMethod.POST)
    @ResponseBody
    public Object memberPay(@RequestParam String deviceNo, @RequestParam String outTradeNo,
                            @RequestParam Long totalFee, @RequestParam String subOpenId) {
        SysUser user = getUserInfo();
        if (user == null) {
            return Result.fail("请登录收银员账号！！");
        }
        if (StringUtils.isBlank(subOpenId)) {
            return Result.fail("用户信息异常！");
        }
        Device device = deviceService.selectByDeviceNo(deviceNo);
        if (device == null) {
            return Result.fail("设备配置信息异常！");
        }
        //获取门店信息
        Store store = storeService.getById(device.getStoreId());
        if (store == null) {
            return Result.fail("门店配置信息异常！");
        }
        Merchant merchant = merchantService.getById(store.getMerchantId());
        if (merchant == null) {
            return Result.fail("商户配置信息异常！");
        }

        Member member = memberService.selectByMerchantIdAndSubOpenIdAndStatus(store.getMerchantId(), subOpenId, 1);
        if (member == null) {
            return Result.fail("未注册会员！");
        }
        MemberLevel level = memberLevelService.getById(member.getMemberLevelId());
        if (level == null) {
            return Result.fail("会员信息异常");
        }
        Long memberFee = (long) (totalFee * level.getDiscount());
        log.debug("memberFee==" + memberFee);
        memberFee = memberFee < 1 ? 1 : memberFee;
        //余额不足
        if (member.getTotalBalances() < memberFee) {
            Map map = new HashMap();
            map.put("totalFee", totalFee);
            map.put("memberFee", memberFee);
            map.put("phone", member.getMobile());
            map.put("status", 0);
            map.put("totalBalances", member.getTotalBalances());
            map.put("msg", "余额不足，请扫码或刷脸支付");
            return Result.success(map);
        } else {
            Map map = new HashMap();
            try {
                TOrder order = tOrderService.payByBalance(deviceNo, totalFee, memberFee, member.getId(), outTradeNo, user.getId());
                map.put("status", 1);
                Member newMember = memberService.getById(member.getId());
                map.put("totalBalances", newMember.getTotalBalances());
                BigDecimal bg = new BigDecimal(memberFee * 0.01);
                DecimalFormat df1 = new DecimalFormat("0.00");
                String fee = df1.format(bg);
                map.put("msg", "余额消费：" + fee + "元");
                map.put("storeName", store.getName());
                map.put("logoUrl", merchant.getLogoUrl());
                //打印数据
                map.put("orderTime", order.getCreatedTime());//下单时间
                map.put("payType", (order.getPayType() == 1 || order.getPayType() == 2) ? "微信" : (order.getPayType() == 3 || order.getPayType() == 4) ? "支付宝" : "余额支付");//下单时间
                map.put("totalFee", order.getOrderTotalFee());//订单金额
                map.put("memberFee", order.getMemberTotalFee());//会员金额
                map.put("settlementTotalFee", order.getSettlementTotalFee());//会员金额
                map.put("realFee", order.getRealPayFee());//实付金额
                map.put("transactionId", order.getTransactionId());//微信订单号
                map.put("deviceNo", order.getDeviceNo());//设备编号
                return Result.success(map);
            } catch (Exception e) {
                map.put("totalFee", totalFee);
                map.put("memberFee", memberFee);
                map.put("phone", member.getMobile());
                map.put("status", 0);
                map.put("totalBalances", member.getTotalBalances());
                map.put("msg", e.getMessage());
                return Result.success(map);
            }
        }
    }

    /**
     * 获取调用凭证(
     *
     * @param rawdata  机器授权码
     * @param deviceNo 机器序列号
     * @return
     */
    @ApiOperation(value = "获取设备授权码", notes = "获取设备授权码", httpMethod = "POST")
    @RequestMapping(value = "/getauthcode", method = RequestMethod.POST)
    @ResponseBody
    public Object getWxpayfaceAuthinfo(@RequestParam String rawdata, @RequestParam String deviceNo) {
        try {
            if (StringUtils.isBlank(rawdata) || StringUtils.isBlank(deviceNo)) {
                return Result.fail("参数错误");
            }

            //获取设备信息
            Device device = deviceService.selectByDeviceNo(deviceNo);
            if (device == null) {
                return Result.fail("设备配置未找到，或未注册");
            }
            //获取门店信息
            Store store = storeService.getById(device.getStoreId());
            if (store == null) {
                return Result.fail("设备未分配门店");
            }
            //获取商户信息
            Merchant merchant = merchantService.getById(store.getMerchantId());
            if (merchant == null) {
                return Result.fail("商户信息异常");
            }
            String outTradeNo = tradeNoService.getTradeNo();
            //String outTradeNo = device.getId() + System.currentTimeMillis() + ApplicationUtils.getRandomStr(5);
            if (merchant.getPayWay() == 0) {//微信原生人脸
                AuthinfoRequest request = new AuthinfoRequest();
                request.setSignType(WxPayConstants.SignType.MD5);
                request.setRawdata(rawdata);
                request.setStoreId(store.getId().toString());
                request.setStoreName(store.getName());
                request.setDeviceId(deviceNo);
                request.setNow((System.currentTimeMillis() + "").substring(0, 10));
                request.setVersion("1");

                request.setSubAppId(merchant.getSubAppId());
                request.setSubMchId(merchant.getSubMchId());
                WxPayServiceExt wxPayServiceExt = weixinPayService.getServiceExt(store.getCode(), merchant.getSubMchId());

                AuthinfoResponse authinfo = wxPayServiceExt.getWxpayfaceAuthinfo(request);

                Map map = new HashMap();
                map.put("appid", authinfo.getAppid());
                map.put("mchId", authinfo.getMchId());
                map.put("subAppId", merchant.getSubAppId());
                map.put("subMchId", authinfo.getSubMchId());
                map.put("storeId", authinfo.getStoreId());
                map.put("authinfo", authinfo.getAuthinfo());
                map.put("outTradeNo", outTradeNo);
                return Result.success(map);
            } else {
                Map<String, String> params = new HashMap();
                params.put("account", merchant.getPayAccount());
                params.put("storeId", store.getId() + "");
                params.put("storeName", store.getName());
                params.put("deviceId", deviceNo);
                params.put("attach", "");
                params.put("rawdata", rawdata);
                params.put("lowOrderId", outTradeNo);
                //设置签名
                String mchKey = merchant.getPayKey();
                try {
                    params.put("sign", MD5Utils.doSign(params, mchKey));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                String url = tytUrl + "/tgPosp/services/payApi/wxFace";

                String str = HttpClientUtils.post(url, JSON.toJSONString(params), "UTF-8");
                JSONObject object = JSONObject.parseObject(str);
                if (object.getInteger("status") == 100) {
                    Map map = new HashMap();
                    map.put("appid", object.getString("appid"));
                    map.put("mchId", object.getString("mchId"));
                    map.put("subAppId", object.getString("subAppId"));
                    map.put("subMchId", object.getString("subMchId"));
                    map.put("storeId", object.getString("storeId"));
                    map.put("authinfo", object.getString("authinfo"));
                    map.put("outTradeNo", outTradeNo);
                    return Result.success(map);
                }
            }
        } catch (WxPayException e) {
            return Result.fail(e.getErrCodeDes());
        }
        return null;
    }

    /**
     * 人脸订单支付
     *
     * @param faceCode   支付人脸识别码
     * @param deviceNo   设备编号
     * @param totalFee   订单金额
     * @param memberFee  会员价格
     * @param outTradeNo 商户订单号
     * @return
     */
    @ApiOperation(value = "人脸订单支付（token验证：header ：Access-Token）", notes = "人脸订单支付（token验证：header ：Access-Token）", httpMethod = "POST")
    @RequestMapping(value = "/payorder", method = RequestMethod.POST)
    @ResponseBody
    public Object payorder(@RequestParam String faceCode, @RequestParam String deviceNo,
                           @RequestParam Integer totalFee, Integer memberFee, String phone, String outTradeNo) throws Exception {
        SysUser user = getUserInfo();
        if (user == null) {
            return Result.fail("请登录收银员账号！！");
        }
        //获取设备信息
        Device device = deviceService.selectByDeviceNo(deviceNo);
        if (device == null) {
            return Result.fail("设备配置未找到，或未注册");
        }
        //获取门店信息
        Store store = storeService.getById(device.getStoreId());
        if (store == null) {
            return Result.fail("设备未分配门店");
        }
        //获取商户信息
        Merchant merchant = merchantService.getById(store.getMerchantId());
        if (merchant == null) {
            return Result.fail("商户信息异常");
        }
        TOrder order1 = tOrderService.selectByOutTradeNo(outTradeNo);
        if (order1 != null) { //订单已存在
            return Result.fail("请不要重复唤起支付！");
        }
        /*支付宝条码支付*/
        if (faceCode != null && ApplicationUtils.isContains(faceCode)) {
            TOrder tOrder = tOrderService.aliBarCodePay(faceCode, deviceNo, totalFee, memberFee, outTradeNo, user.getId());
            if (tOrder != null) {
                return Result.success("支付成功！");
            } else {
                return Result.fail("订单支付失败");
            }
        } else {
            if (merchant.getPayWay() == 0) {//执行微信人脸支付
                try {
                    TOrder order = tOrderService.createFacePayOrder(faceCode, deviceNo, totalFee, memberFee, phone, outTradeNo, user.getId());
                    if (order != null && order.getOrderStatus() == 1) {
                        return Result.success(order.getOutTradeNo());
                    } else {
                        return Result.fail("订单支付失败");
                    }
                } catch (Exception e) {
                    log.error("人脸订单支付:" + e.getMessage());
                    return Result.fail(e.getMessage());
                }
            } else if (merchant.getPayWay() == 1) {//执行银行支付（通用通）
                if (StringUtils.isBlank(merchant.getPayAccount()) || StringUtils.isBlank(merchant.getPayKey())) {
                    return Result.fail("支付通道配置异常");
                }
                try {
                    TOrder order = tOrderService.createTytPayOrder(faceCode, deviceNo, totalFee, memberFee, phone, outTradeNo, user.getId());
                    if (order != null && order.getOrderStatus() == 1) {
                        return Result.success(order.getOutTradeNo());
                    } else {
                        return Result.fail("订单支付失败");
                    }
                } catch (Exception e) {
                    log.error("人脸订单支付:" + e.getMessage());
                    return Result.fail(e.getMessage());
                }
            } else {
                return Result.fail("订单支付失败");
            }
        }
    }

    /**
     * 创建扫码预支付订单
     *
     * @return
     */
    @ApiOperation(value = "创建扫码预支付订单", notes = "创建扫码预支付订单", httpMethod = "GET")
    @RequestMapping(value = "/createScanOrder", method = RequestMethod.GET)
    @ResponseBody
    public Object getOrderNo(@RequestParam String deviceNo, @RequestParam Integer totalFee,
                             Integer memberFee, String phone) {
        log.info("创建扫码预支付订单");

        SysUser user = getUserInfo();
        if (user == null) {
            return Result.fail("请登录收银员账号！！");
        }
        String token = request.getHeader("Access-Token");

        Device device = deviceService.selectByDeviceNo(deviceNo);
        if (device == null) {
            return Result.fail("设备配置信息异常！");
        }
        //获取门店信息
        Store store = storeService.getById(device.getStoreId());
        if (store == null) {
            return Result.fail("门店配置信息异常！");
        }
        Merchant merchant = merchantService.getById(store.getMerchantId());
        if (merchant == null) {
            return Result.fail("商户配置信息异常！");
        }
        String outTradeNo = tradeNoService.getTradeNo();
        //组装微信支付宝扫码链接
        String qrUrl = notifyUrl + "/open/scanPayOrder?deviceNo=" + deviceNo;
        qrUrl += "&accessToken=" + token;
        qrUrl += "&outTradeNo=" + outTradeNo;
        qrUrl += "&totalFee=" + totalFee;
        if (memberFee != null && memberFee > 0l && StringUtils.isNotBlank(phone)) {
            qrUrl += "&memberFee=" + memberFee;
            qrUrl += "&phone=" + phone;
        }

        if (merchant.getPayWay() == 0) { //微信支付宝原生扫码
            qrUrl += "&payWay=" + 0;
        } else { //微信支付宝第三方扫码
            try {
                qrUrl += "&payWay=" + 1;
                String redirectUrl = tOrderService.createTytScanPayOrder(deviceNo, outTradeNo, totalFee, memberFee, phone, user.getId());
                qrUrl += "&redirectUrl=" + redirectUrl;
            } catch (Exception e) {
                return Result.fail(e.getMessage());
            }
        }
        Map map = new HashMap();
        map.put("qrUrl", qrUrl);
        map.put("outTradeNo", outTradeNo);
        return Result.success(map);
    }

    /**
     * 查询订单结果
     *
     * @return
     */
    @ApiOperation(value = "查询订单", notes = "查询订单", httpMethod = "GET")
    @RequestMapping(value = "/getOrder", method = RequestMethod.GET)
    @ResponseBody
    public Result getOrder(@RequestParam String outTradeNo) {
        SysUser user = getUserInfo();
        if (user == null) {
            return Result.fail("请登录收银员账号！！");
        }
        if (StringUtils.isBlank(outTradeNo)) {
            return Result.fail("参数错误");
        }
        TOrder order = tOrderService.selectByOutTradeNo(outTradeNo);
        if (order == null) {
            return Result.fail("订单查询失败（订单信息异常）");
        }
        Merchant merchant = merchantService.getById(order.getMerchantId());
        if (merchant == null) {
            return Result.fail("订单查询失败（商户信息异常）");
        }
        ServiceBusiness serviceBusiness = serviceBusinessService.getById(order.getBusinessServiceId());
        if (serviceBusiness == null) {
            return Result.fail("订单查询失败（服务商信息异常）");
        }
        Map map = new HashMap();
        //交易上报数据
        map.put("mchId", serviceBusiness.getWxMchId());
        map.put("subMchId", merchant.getSubMchId());
        map.put("outTradeNo", outTradeNo);
        map.put("status", order.getOrderStatus() == 1 ? "已支付" : order.getOrderStatus() == 5 ? "押金支付" : order.getOrderStatus() == 3 ? "已退款" : "支付失败");
        //打印数据
        map.put("storeName", order.getStoreName());//门店名称
        map.put("orderTime", order.getCreatedTime());//下单时间
        map.put("payType", order.getPayType() == 1 ? "微信" : order.getPayType() == 2 ? "支付宝" : order.getPayType() == 3 ? "会员支付" : "通用通");//下单时间
        map.put("totalFee", order.getOrderTotalFee());//订单金额
        map.put("memberFee", order.getMemberTotalFee());//会员金额
        map.put("settlementTotalFee", order.getSettlementTotalFee());//会员金额
        map.put("realFee", order.getRealPayFee());//实付金额
        map.put("consumeFee", order.getOrderTotalFee() - order.getDepositFee());//消费金额
        map.put("depositFee", order.getDepositFee());//押金金额
        map.put("transactionId", order.getTransactionId());//微信订单号
        map.put("deviceNo", order.getDeviceNo());//设备编号
        map.put("userName", user.getRealName());//当前用户姓名
        return Result.success(map);
    }


    /**
     * 查询订单结果
     *
     * @return
     */
    @ApiOperation(value = "查询最后一笔支付订单", notes = "查询最后一笔支付订单", httpMethod = "GET")
    @RequestMapping(value = "/getLastOrderPrint", method = RequestMethod.GET)
    @ResponseBody
    public Result getLastOrderPrint(@RequestParam String deviceNo) {
        SysUser user = getUserInfo();
        if (user == null) {
            return Result.fail("请登录收银员账号！！");
        }
        if (StringUtils.isBlank(deviceNo)) {
            return Result.fail("参数错误");
        }
        TOrder order = tOrderService.selectLastByUserIdAndDeviceNo(user.getId(), deviceNo);
        if (order == null) {
            return Result.fail("当前账号未查询到订单信息");
        }
        Merchant merchant = merchantService.getById(order.getMerchantId());
        if (merchant == null) {
            return Result.fail("订单查询失败（商户信息异常）");
        }
        ServiceBusiness serviceBusiness = serviceBusinessService.getById(order.getBusinessServiceId());
        if (serviceBusiness == null) {
            return Result.fail("订单查询失败（服务商信息异常）");
        }
        Map map = new HashMap();
        //交易上报数据
        map.put("mchId", serviceBusiness.getWxMchId());
        map.put("subMchId", merchant.getSubMchId());
        map.put("outTradeNo", order.getOutTradeNo());
        map.put("status", order.getOrderStatus() == 1 ? "已支付" : order.getOrderStatus() == 5 ? "押金支付" : order.getOrderStatus() == 3 ? "已退款" : "支付失败");
        //打印数据
        map.put("storeName", order.getStoreName());//门店名称
        map.put("orderTime", order.getCreatedTime());//下单时间
        map.put("payType", order.getPayType() == 1 ? "微信" : order.getPayType() == 2 ? "支付宝" : order.getPayType() == 3 ? "会员支付" : "通用通");//下单时间
        map.put("totalFee", order.getOrderTotalFee());//订单金额
        map.put("memberFee", order.getMemberTotalFee());//会员金额
        map.put("settlementTotalFee", order.getSettlementTotalFee());//会员金额
        map.put("realFee", order.getRealPayFee());//实付金额
        map.put("consumeFee", order.getOrderTotalFee() - order.getDepositFee());//消费金额
        map.put("depositFee", order.getDepositFee());//押金金额
        map.put("transactionId", order.getTransactionId());//微信订单号
        map.put("deviceNo", order.getDeviceNo());//设备编号
        map.put("userName", user.getRealName());//当前用户姓名
        return Result.success(map);
    }

    /**
     * 查询订单结果
     *
     * @return
     */
    @ApiOperation(value = "根据id查询订单", notes = "根据id查询订单", httpMethod = "GET")
    @RequestMapping(value = "/getOrderById", method = RequestMethod.GET)
    @ResponseBody
    public Result getOrderById(@RequestParam Long id) {
        TOrder order = tOrderService.getById(id);
        if (order == null) {
            return Result.fail("订单查询失败（订单信息异常）");
        }
        Merchant merchant = merchantService.getById(order.getMerchantId());
        if (merchant == null) {
            return Result.fail("订单查询失败（商户信息异常）");
        }
        ServiceBusiness serviceBusiness = serviceBusinessService.getById(order.getBusinessServiceId());
        if (serviceBusiness == null) {
            return Result.fail("订单查询失败（服务商信息异常）");
        }
        return Result.success(order);
    }

    /**
     * 获取广告列表
     *
     * @return
     */
    @ApiOperation(value = "获取广告列表", notes = "获取广告列表", httpMethod = "GET")
    @RequestMapping(value = "/getAdvertList", method = RequestMethod.GET)
    @ResponseBody
    public Object getAdvertList(@RequestParam String deviceNo) {
        if (StringUtils.isBlank(deviceNo)) {
            return Result.fail("设备编号不能为空");
        }
        Map result = new HashMap();
        List<Advertisement> advertisements = advertisementService.selectRightPlusByDeviceNo(deviceNo);
        JSONArray videoList = new JSONArray();
        JSONArray picList = new JSONArray();
        if (advertisements != null) {
            for (Advertisement advertisement : advertisements) {
                if (advertisement.getSourceType() == 0) {/*图片*/
                    JSONObject picObject = new JSONObject();
                    picObject.put("url", advertisement.getSourceUrl());
                    picObject.put("type", "pic");
                    picObject.put("displayTime", advertisement.getDisplayTime());
                    picList.add(picObject);
                } else if (advertisement.getSourceType() == 1) {
                    JSONObject videoObject = new JSONObject();
                    videoObject.put("url", advertisement.getSourceUrl());
                    videoObject.put("type", "video");
                    videoObject.put("displayTime", advertisement.getDisplayTime());
                    videoList.add(videoObject);
                }
            }
        }
        result.put("video", videoList);
        result.put("pic", picList);
        return Result.success(result);
    }

    /**
     * 获取商户公众号二维码
     *
     * @return
     */
    @ApiOperation(value = "获取商户公众号二维码", notes = "获取商户公众号二维码", httpMethod = "GET")
    @RequestMapping(value = "/getAppQrCode", method = RequestMethod.GET)
    @ResponseBody
    public Object getAppQrCode(@RequestParam String deviceNo) {
        if (StringUtils.isBlank(deviceNo)) {
            return Result.fail("设备编号不能为空");
        }
        //获取设备信息
        Device device = deviceService.selectByDeviceNo(deviceNo);
        if (device == null) {
            return Result.fail("设备配置未找到，或未注册");
        }
        //获取门店信息
        Store store = storeService.getById(device.getStoreId());
        if (store == null) {
            return Result.fail("设备未分配门店");
        }
        //获取商户信息
        Merchant merchant = merchantService.getById(store.getMerchantId());
        if (merchant == null) {
            return Result.fail("商户信息异常");
        }
        if (StringUtils.isBlank(merchant.getSubAppAccount())) {
            return Result.fail("商户未配置公众号原始ID");
        }
        String qrUrl = "https://open.weixin.qq.com/qr/code?username=" + merchant.getSubAppAccount();

        return Result.success(qrUrl);
    }

    /**
     * 获取注册用户验证码
     *
     * @return
     */
    @GetMapping("/getValidateCode")
    @ResponseBody
    public Result getValidateCode(String phone) {
        log.debug(phone + "获取手机验证码");
        try {
            String code = memberService.getValidateCode(phone);
            if (StringUtils.isNotBlank(code)) {
                return Result.success();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.fail("获取验证码失败");

    }

    /**
     * 获取结算数据
     *
     * @return
     */
    @ApiOperation(value = "获取结算数据", notes = "获取结算数据", httpMethod = "GET")
    @GetMapping("/getCloseAccount")
    @ResponseBody
    public Result getCloseAccount(String deviceNo) {
        try {
            SysUser user = getUserInfo();
            if (user == null) {
                return Result.fail("请登录收银员账号！！");
            }
            Object data = tOrderService.getCloseAccount(deviceNo, user);
            return Result.success(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.fail("获取结算数据失败！");

    }

    @ApiOperation(value = "查询结算单列表", notes = "查询结算单列表", httpMethod = "POST")
    @RequestMapping(value = "/selectCloseAccountList/{pageNum}/{pageSize}", method = RequestMethod.POST)
    @ResponseBody
    public Result selectCloseAccountList(@ApiParam(value = "当前页", required = true) @PathVariable("pageNum") Integer pageNum,
                                         @ApiParam(value = "每页大小", required = true) @PathVariable("pageSize") Integer pageSize,
                                         @RequestBody @ApiParam(name = "closeAccount", value = "传入json格式") CloseAccount closeAccount) {
        SysUser user = getUserInfo();

        if (user == null) {
            return Result.fail("请登录收银员账号！！");
        }
        if (closeAccount == null) {
            return Result.fail("参数不能为空！");
        }

        if (closeAccount.getDeviceNo() == null) {
            return Result.fail("设备编号参数不能为空！");
        }
        closeAccount.setStoreUserId(user.getId());
        IPage<CloseAccount> closeAccountIPage = closeAccountService.selectList(pageSize, pageNum, closeAccount);
        return Result.success(closeAccountIPage);

    }

    @ApiOperation(value = "退款申请", notes = "退款申请", httpMethod = "GET")
    @RequestMapping(value = "/refund", method = RequestMethod.GET)
    @ResponseBody
    public Result refund(@ApiParam(value = "外部订单编号", required = true) @RequestParam String outTradeNo,
                         @ApiParam(value = "商户退款密码", required = true) @RequestParam String refundSecret
    ) {

        SysUser user = getUserInfo();
        if (user == null) {
            return Result.fail("请登录账号！！");
        }

        if (StringUtils.isBlank(outTradeNo)) {
            return Result.fail("外部订单号不能为空！");
        }
        if (StringUtils.isBlank(refundSecret)) {
            return Result.fail("商户退款密码不能为空！");
        }
        TOrder tOrder = tOrderService.selectByOutTradeNo(outTradeNo);
        if (tOrder == null) {
            return Result.fail("订单不存在！");
        }
        if (tOrder.getOrderStatus() == 3) {
            return Result.fail("订单已经退款！");
        }
        Merchant merchant = merchantService.getById(tOrder.getMerchantId());
        if (!refundSecret.equals(merchant.getRefundSecret())) {
            return Result.fail("商户退款密码不正确！");
        }
        boolean flag = false;
        try {
            if (1 == tOrder.getPayType()) {//微信
                flag = tOrderService.refund(tOrder, merchant, user);
            } else if (2 == tOrder.getPayType()) { //支付宝
                flag = tOrderService.aliRefund(tOrder, merchant, user);
            } else if (3 == tOrder.getPayType()) {//会员支付
                flag = tOrderService.memberRefund(tOrder, merchant, user);
            } else if (4 == tOrder.getPayType()) {//通用通
                flag = tOrderService.tytRefund(tOrder, merchant, user);
            } else {

            }
            if (flag) {
                return Result.success("退款成功");
            } else {
                return Result.fail("退款失败");
            }
        } catch (WxPayException e) {
            log.error("退款失败", e);
            return Result.fail("退款失败");
        } catch (Exception e) {
            log.error("退款失败", e);
            return Result.fail("退款失败");
        }
    }

    @ApiOperation(value = "退款申请结果查询", notes = "退款申请结果查询", httpMethod = "GET")
    @RequestMapping(value = "/refundQuery", method = RequestMethod.GET)
    @ResponseBody
    public Result refundQuery(@ApiParam(value = "外部订单编号", required = true) @RequestParam String outTradeNo) {
        if (StringUtils.isBlank(outTradeNo)) {
            return Result.fail("外部订单号不能为空！");
        }
        TOrder tOrder = tOrderService.selectByOutTradeNo(outTradeNo);
        if (tOrder == null) {
            return Result.fail("订单不存在！");
        }
        Merchant merchant = merchantService.getById(tOrder.getMerchantId());
        try {
            boolean flag = tOrderService.refundQuery(tOrder, merchant);
            if (flag) {
                return Result.success("退款成功");
            } else {
                return Result.fail("退款失败");
            }
        } catch (WxPayException e) {
            return Result.fail("退款失败");
        } catch (Exception e) {
            return Result.fail("退款失败");
        }
    }

    /**
     * 查询订单列表
     *
     * @param pageNum    页码
     * @param pageSize   每页条数
     * @param deviceNo   设备编号
     * @param beginTime  开始时间
     * @param outTradeNo 订单号
     * @return
     */
    @ApiOperation(value = "查询订单列表", notes = "查询订单列表", httpMethod = "POST")
    @RequestMapping(value = "/getOrderList/{pageNum}/{pageSize}", method = RequestMethod.POST)
    @ResponseBody
    public Result getOrderList(@ApiParam(value = "当前页", required = true) @PathVariable("pageNum") Integer pageNum,
                               @ApiParam(value = "每页大小", required = true) @PathVariable("pageSize") Integer pageSize,
                               @ApiParam(value = "设备号", required = true) @RequestParam("deviceNo") String deviceNo,
                               String beginTime,
                               String outTradeNo) {
        if (StringUtils.isBlank(deviceNo)) {
            return Result.fail("设备编号错误");
        }
        try {
            IPage<TOrder> page = tOrderService.selectListByDeviceNoAndTime(pageNum, pageSize, deviceNo, beginTime, outTradeNo);
            return Result.success(page);
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }


    /**
     * 查询打印订单列表（全部数据）
     *
     * @param deviceNo  设备编号
     * @param beginTime 开始时间
     * @return
     */
    @ApiOperation(value = "查询打印订单列表（全部数据）", notes = "查询打印订单列表（全部数据）", httpMethod = "POST")
    @RequestMapping(value = "/getOrderListPrint", method = RequestMethod.POST)
    @ResponseBody
    public Result getOrderListPrint(@ApiParam(value = "设备号", required = true) @RequestParam("deviceNo") String deviceNo,
                                    String beginTime) {
        if (StringUtils.isBlank(deviceNo)) {
            return Result.fail("设备编号错误");
        }
        try {
            Object obj = tOrderService.selectListByDeviceNoAndTimeAll(deviceNo, beginTime);
            return Result.success(obj);
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }


    /**
     * 查询打印结算信息（全部数据）
     *
     * @param deviceNo  设备编号
     * @param beginTime 开始时间
     * @return
     */
    @ApiOperation(value = "查询打印结算信息（全部数据）", notes = "查询打印结算信息（全部数据）", httpMethod = "POST")
    @RequestMapping(value = "/getCloseAccountPrint", method = RequestMethod.POST)
    @ResponseBody
    public Object getCloseAccountPrint(@ApiParam(value = "设备号", required = true) @RequestParam("deviceNo") String deviceNo,
                                       String beginTime) {
        if (StringUtils.isBlank(deviceNo)) {
            return Result.fail("设备编号错误");
        }
        SysUser user = getUserInfo();
        if (user == null) {
            return Result.fail("请登录收银员账号！！");
        }
        try {
            Object data = tOrderService.getCloseAccountPrint(deviceNo, beginTime,user);
            return Result.success(data);
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }
}
